#include "unitInstance.h"


#include "UnitInstance.h"
#include "freefuncs.h"
#include <string>
#include <iostream>
#include <math.h>
using namespace std;

int UnitInstance::getFeature (int i)
{
	return this->feature.getFeature(i);;
}

int UnitInstance::getLabel (void)
{
	return this->label;
}

int UnitInstance::getOccuranceNum (void)
{
	return this->occurrenceNum;
}

int UnitInstance::getConflictNum (void)
{
	return this->conflictNum;
}

unsigned long UnitInstance::getHash (void)
{
	return this->featureHash;
}

void UnitInstance::setFeature (int i, int value)
{
	this->feature.setFeature(i, value);
}

void UnitInstance::setLabel (int value)
{
	this->label = value;
}

void UnitInstance::setOccurrenceNum (int value)
{
	this->occurrenceNum = value;
}

void UnitInstance::incrementOccurrenceNum(void)
{
	this->occurrenceNum++;
}

void UnitInstance::setConflictNum (int value)
{
	this->conflictNum = value;
}

void UnitInstance::incrementConflictNum(void)
{
	this->conflictNum++;
}

void UnitInstance::updateFeatureHash (void)
{
	unsigned long result = 0;
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2); i++)
		result += this->feature.getFeature(i) * intPosPow(CELLSTATES, i);
	this->featureHash = result;
}

bool UnitInstance::hasSameFeature (UnitInstance& other)
{
	int i = 0;
	while ( i++ != intPosPow((2*NRADIUS+1),2) && this->feature.getFeature(i) == other.feature.getFeature(i) );
	if (i == intPosPow((2*NRADIUS+1),2))
		return true;
	else
		return false;
}



UnitInstance & UnitInstance::operator= (UnitInstance& other)
{
	if (&other == this)
		return *this;
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2); i++)
		this->feature.setFeature(i, other.feature.getFeature(i));

	this->conflictNum = other.conflictNum;
	this->featureHash = other.featureHash;
	this->label = other.label;
	this->occurrenceNum = other.occurrenceNum;

	return * this;
}

UnitInstance::UnitInstance ()
{
	this->conflictNum = 0;
	this->featureHash = 0;
	this->label = 0;
	this->occurrenceNum = 0;
}


UnitInstance::UnitInstance (string bitString, int label)
{
	cout << "FUNCTION UnitInstance::UnitInstance (string bitString, int label) STILL USES CHAR, SHOULD BE FIXED" << endl;
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2); i++)
		this->feature.setFeature(i, (int)bitString.at(i));
	this->label = label;
	this->updateFeatureHash();
	this->conflictNum = 0;
	this->occurrenceNum = 1;
}

UnitInstance::UnitInstance (int* bitArray, int label)
{
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2); i++)
		this->feature.setFeature(i, bitArray[i]);
	this->label = label;
	this->updateFeatureHash();
	this->conflictNum = 0;
	this->occurrenceNum = 1;
}

UnitInstance::UnitInstance(int hashValue, int label)
{
	int dynamicNum = hashValue;
	this->featureHash = hashValue;
	this->label = label;
	this->conflictNum = 0;
	this->occurrenceNum = 1;
	for (int bitIndex = 0; bitIndex != intPosPow((2*NRADIUS+1),2)-1 ; bitIndex++)
	{
		this->feature.setFeature(bitIndex, dynamicNum % CELLSTATES);
		dynamicNum = dynamicNum / CELLSTATES;
	}
	this->feature.setFeature(intPosPow((2*NRADIUS+1),2)-1, dynamicNum);
}

UnitInstance::UnitInstance(int hashValue, int label, int occurance)
{
	int dynamicNum = hashValue;
	this->featureHash = hashValue;
	this->label = label;
	this->conflictNum = 0;
	this->occurrenceNum = 1;
	for (int bitIndex = 0; bitIndex != intPosPow((2*NRADIUS+1),2)-1 ; bitIndex++)
	{
		this->feature.setFeature(bitIndex, dynamicNum % CELLSTATES);
		dynamicNum = dynamicNum / CELLSTATES;
	}
	this->feature.setFeature(intPosPow((2*NRADIUS+1),2)-1, dynamicNum);
	this->occurrenceNum = occurance;
}

UnitInstance::~UnitInstance()
{
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2); i++)
		this->feature.setFeature(i, 0);
	this->label = 0;
	this->conflictNum = 0;
	this->occurrenceNum = 0;
	this->featureHash = 0;
}

void UnitInstance::print(void)
{
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2)-1; i++)
		cout << this->feature.getFeature(i) << ", ";
	cout << this->feature.getFeature(intPosPow((2*NRADIUS+1),2)-1) << " - " << this->label << endl;
}

void UnitInstance::printDetail(void)
{
	for (int i = 0; i != intPosPow((2*NRADIUS+1),2)-1; i++)
		cout << this->feature.getFeature(i) << ", ";
	cout << this->feature.getFeature(intPosPow((2*NRADIUS+1),2)-1) << " - " << this->label
			<< " ||| featureHash: "<< this->featureHash << ", occurenceNum: " << this->occurrenceNum
			<< ", conflictNum: " << this->conflictNum << endl;
}
